home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / C Internet Config / IC Random Signature ƒ / IC Generic Override.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-17  |  12.6 KB  |  455 lines  |  [TEXT/SPM ]

  1. /*
  2.     IC Generic Overide.c
  3.     
  4.     C port of ICGenericOverride.p, file comment follows below.
  5.     
  6.     I ported all of IC to C, so I figured I might as well do the same
  7.     for all of the other little pieces.
  8.     
  9.     History:
  10.         11/17/95 dhn - Started port.
  11. */
  12.  
  13. /*
  14.     Internet Config Generic Overide Component
  15.  
  16.     Routine names have an ICGO prefix for Internet Config Generic Override.
  17.  
  18.     This component is the framework for an Internet Config override
  19.     component. I've used it to replace the original IC ReadOnly and
  20.     IC RandomSignature components bodies with one common body.
  21.     The different between the two components is now contained isolated
  22.     in a separate file, ICSpecificOverride.
  23.  
  24.     The component overrides the Internet Config Extension and
  25.     passes all calls through to the specific override to determine
  26.     whether it should be overridden.
  27.  
  28.     This code has followed a fairly long path--Jager was the one who
  29.     originally started the work on the Random Signature component.
  30.     I based my code on his code and tried to get it work, in the
  31.     process finding and using some sample code from a develop article.
  32.     Eric translated the generic  parts of Random Signature to C to
  33.     implement a component of his own (fixing bugs and rewriting along
  34.     the way), and then modified to duplicate the behavior of
  35.     IC ReadOnly. Since then I have ported the changes back to Pascal
  36.     to form the basis of this generic override component, which I've
  37.     used for the IC 1.1 override components.
  38.  
  39.     Consider it a collaborative work, as Eric
  40.     says "a bit of a Frankenstein's monster".
  41.  
  42.     This release fixes a nasty bug in the Pascal example components, one which
  43.     prevents them from loading if their manufacturer code comes after
  44.     that of a previously registered component. If you use any component
  45.     based on this code, the old versions of IC ReadOnly and Random
  46.     Signature will probably stop working.
  47.  
  48.     If you're implementing a component of your own, I strongly suggest
  49.     you contact either Eric or myself first. In any event, read
  50.     the section on the component manager in Inside Macintosh: More
  51.     Macintosh Toolbox very closely and test your component thoroughly.
  52.     You'll definitely want some tools off of develop 15, including
  53.     Komponent Killer, Reinstaller II and the "thing" dcmd.
  54.  
  55.     This code is probably of adequate quality for most uses, but if
  56.     you are using it to implement a commercial-quality system, you
  57.     may want to rewrite it from the ground up.
  58.  
  59.     Quinn "The Eskimo!"
  60.  
  61.     with vast plagarism from...
  62.  
  63.     Eric Kidd
  64.     eric.kidd@dartmouth.edu
  65.  
  66.     Thanks for all the work Eric!
  67.  
  68. */
  69.  
  70. #include <Components.h>
  71. #include <Folders.h>
  72.  
  73. #if USESROUTINEDESCRIPTORS
  74. #include <stdlib.h>
  75. #endif
  76.  
  77. #include "IC Keys.h"
  78. #include "IC Component Selectors.h"
  79. #include "IC Component API.h"
  80.  
  81. #include "IC Generic Override.h"
  82. #include "IC Specific Override.h"
  83.  
  84. // #include "IC Component Utils.h"
  85.  
  86. /*
  87.     ICGOFixCloneRefCon
  88.  
  89.     See Inside Macintosh: More Macintosh Toolbox p. 6-35 for
  90.     an overview of this silliness. It seems that when your globally-
  91.     registered component is opened by an application, the system
  92.     pulls a fast one under "certain circumstances" (not enough memory
  93.     in the system heap) and "clones" a locally-registered version
  94.     of your component, frying your RefCon in process.
  95.  
  96.     What we need to do is determine if this is the case, and if so,
  97.     recover the RefCon by locating the original copy of the component.
  98.  
  99.     The Officially Sactioned Way to do this is a bit of a hack. Global
  100.     components have an A5 world of zero when they are opened, but local
  101.     ones have it pre-set to the parent application's value. If your
  102.     supposedly global component detects that it has a pre-set A5 world,
  103.     then it's been cloned.
  104.  
  105.     To find the original copy of the component (which has the RefCon we
  106.     need), we need to find another component that looks exactly like us,
  107.     with the exception of a different component identifier. Unless we've
  108.     been registered globally multiple times under the same name, this
  109.     should work. FindNextComponent will do the job here.
  110.  
  111.     The "practical upshot" of this:
  112.         1) Only call this routine when handling open messages
  113.         2) Call it before setting your instance's A5 world
  114.         3) Only call it if you should have been global
  115.         4) It won't work if you've been registered multiple times
  116.             under the same name.
  117.         5) Don't use the same manufacturer code for different
  118.             components with the same type/subtype
  119.         6) It may not work at all. I'm a college student, dammit, not a
  120.             programming guru.
  121.  
  122.     Eric Kidd
  123.     eric.kidd@dartmouth.edu
  124.     16 Dec 94
  125. */
  126. pascal ComponentResult ICGOFixCloneRefCon(ComponentInstance self){
  127.     OSErr err=noErr;
  128.     ComponentDescription cd;
  129.     Component current;
  130.     
  131.     if ((GetComponentRefcon((Component)self)==0)&&(GetComponentInstanceA5(self)!=0)){
  132.         // if this component has not been opened & setup and we've been cloned
  133.         
  134.         // get enough info about ourself to recognize the original
  135.         GetComponentInfo((Component)self,&cd,0,0,0);
  136.         cd.componentFlagsMask=0L; // these shouldn't be relevant
  137.         
  138.         current=(Component)0;
  139.         
  140.         do {
  141.             // loop until we find someone other than ourself
  142.             current=FindNextComponent(current,&cd);
  143.             
  144.             if (current==(Component)0){
  145.                 // We didn't find any original--this happens often.
  146.                 // If we've been captured, we can't find the original copy.
  147.                 // Best thing to do is return an error.
  148.                 return paramErr;
  149.             }
  150.         } while (current!=(Component)self);
  151.         
  152.         if (current!=(Component)0)
  153.             SetComponentRefcon((Component)self,GetComponentRefcon(current));
  154.         
  155.         err=noErr;
  156.     }
  157.     
  158.     return err;
  159. }
  160.  
  161. /*
  162.     If the shared globals have not yet been allocated, we'll try to set them up and return them.
  163. */
  164. pascal ComponentResult ICGOGetSharedGlobals(GlobalsHandle globals){
  165.     ComponentResult err;
  166.     SharedGlobalsPtr shared;
  167.     
  168.     shared=(SharedGlobalsPtr)GetComponentRefcon((Component)(*globals)->self);
  169.     (*globals)->shared=shared;
  170.     
  171.     if (shared==(SharedGlobalsPtr)0){
  172.         shared=(SharedGlobalsPtr)NewPtrSysClear(sizeof(SharedGlobals));
  173.         err=MemError();
  174.         (*globals)->shared=(SharedGlobalsPtr)0;
  175.         
  176.         if (err!=noErr)
  177.             return err;
  178.         
  179.         (*globals)->shared=shared;
  180.         
  181.         // init our part of the shared globals
  182.         shared->delegate=0;
  183.         
  184.         // and remember the shared globals in our refcon
  185.         
  186.         SetComponentRefcon((Component)(*globals)->self,(long)shared);
  187.         
  188.         // Since our shared globals get set up only once at registration time,
  189.         // here's the perfect place to move ourselves to the default position in the component list
  190.         
  191.         err=SetDefaultComponent((Component)(*globals)->self,defaultComponentIdentical+defaultComponentAnyFlagsAnyManufacturer);
  192.         
  193.         if (err==noErr)
  194.             ICSOInitShared(globals);
  195.     }
  196.     
  197.     return err;
  198. }
  199.  
  200. // Component Manager Routines
  201.  
  202. /*
  203.     I'd love to allocate shared globals here, but certain versions of the Component Manager
  204.     don't call ICGORegister.  Additionally, calls to ICGOOpen and ICGOClose bracket the call if it
  205.     does get made.  Go Figure.
  206.     
  207.     We actually return a boolean value, false if we should be registered and true if we shouldn't.
  208. */
  209. pascal ComponentResult ICGORegister(GlobalsHandle globals){
  210.     
  211.     return (ComponentResult)false;
  212. }
  213.  
  214. /*
  215.     Eric's comment:
  216.         Does this break if we've been cloned? Does the clone get unregistered seperately and double dispose? Hmm.
  217.     FIIK )-:
  218. */
  219. pascal ComponentResult ICGOUnregister(GlobalsHandle globals){
  220.     ComponentResult result=-1,result2;
  221.     
  222.     if ((*globals)->shared!=(SharedGlobalsPtr)0){
  223.         // give the specifics opportunity to clean up its shared globals
  224.         
  225.         result=ICSOCleanShared(globals);
  226.         
  227.         // clean up our part of the shared globals
  228.         result2=UncaptureComponent((*globals)->shared->delegate);
  229.         
  230.         if (result==noErr)
  231.             result=result2;
  232.         
  233.         // dispose of the shared globals and set our refcon back to zero
  234.         
  235.         DisposePtr((Ptr)(*globals)->shared);
  236.         SetComponentRefcon((Component)(*globals)->self,0L);
  237.     }
  238.     
  239.     return result;
  240. }
  241.  
  242. /*
  243.     Handle the Component Manager CanDo request.
  244. */
  245. pascal ComponentResult ICGOCanDo(GlobalsHandle globals,short selector){
  246.     ComponentResult result;
  247.     
  248.     switch (selector){
  249.         case kComponentUnregisterSelect:
  250.         case kComponentOpenSelect:
  251.             result=(ComponentResult)1;
  252.             break;
  253.         default:
  254.             result=ICSOCanDo(globals,selector);
  255.             
  256.             if (result==delegateThisCallErr)
  257.                 result=ComponentFunctionImplemented((*globals)->delegate,selector);
  258.             else
  259.                 result++;
  260.             break;
  261.     }
  262.     
  263.     return result;
  264. }
  265.  
  266. pascal Component ICGOFindDelegate(Component after){
  267.     ComponentDescription cd;
  268.     ComponentDescription found_cd;
  269.     Component current;
  270.     Boolean found=false;
  271.     
  272.     cd.componentType=internetConfigurationComponentType;
  273.     cd.componentSubType=internetConfigurationComponentSubType;
  274.     cd.componentManufacturer=(OSType)0;
  275.     cd.componentFlags=0L;
  276.     cd.componentFlagsMask=0L;
  277.     
  278.     current=after;
  279.     
  280.     do {
  281.         current=FindNextComponent(current,&cd);
  282.         
  283.         if (current!=(Component)0){
  284.             if (GetComponentInfo(current,&found_cd,0,0,0)==noErr){
  285.                 found=(found_cd.componentManufacturer!=kOurComponentManufacturer);
  286.             }
  287.         }
  288.     } while ((!found)&&(current!=(Component)0));
  289.     
  290.     if (current==(Component)0){
  291.         // DebugStr("\pICGOFindDelegate failed to find one.");
  292.     }
  293.     
  294.     return current;
  295. }
  296.  
  297. /*
  298.     ICGOOpen
  299.     
  300.     This function has been substantially recrafted from the original.  Cloning
  301.     is now handled correctly (see the description of ICGOFixCloneRefCon and error
  302.     handling has been made more graceful by the addition of a dedicated control
  303.     structure.  A memory leak has been closed and OpenComponent can no longer
  304.     be called on a NULL component instance.
  305.     
  306.     If you're using the pascal version, you'll want to carefully examine the differences.
  307. */
  308. pascal ComponentResult ICGOOpen(GlobalsHandle globals,ComponentInstance self){
  309.     ComponentResult err;
  310.     Component cap,toCapture;
  311.     
  312.     globals=(GlobalsHandle)0;
  313.     err=ICGOFixCloneRefCon(self);
  314.     
  315.     if (err==noErr){
  316.         globals=(GlobalsHandle)NewHandleClear(sizeof(GlobalsRecord));
  317.         err=MemError();
  318.     }
  319.     
  320.     if (err==noErr){
  321.         HLock((Handle)globals);
  322.         (*globals)->self=self;
  323.         SetComponentInstanceStorage(self,(Handle)globals);
  324.         err=ICGOGetSharedGlobals(globals);
  325.     }
  326.     
  327.     if (err==noErr){
  328.         // if we haven't yet done so, find and capture the topmost IC component.  We'll
  329.         // save the special component identifier which will permit us to open it.
  330.         
  331.         if ((*globals)->shared->delegate==0){
  332.             toCapture=ICGOFindDelegate((Component)self);
  333.             
  334.             if (toCapture==(Component)0)
  335.                 err=icNothingToOverrideErr;
  336.             else
  337.                 (*globals)->shared->delegate=CaptureComponent(toCapture,(Component)self);
  338.         }
  339.         
  340.         if (err==noErr){
  341.             (*globals)->delegate=OpenComponent((*globals)->shared->delegate);
  342.             err=ComponentSetTarget(self,self);
  343.         }
  344.         if (err==noErr)
  345.             err=ICSOInitGlobals(globals);
  346.     }
  347.     
  348.     if (globals!=(GlobalsHandle)0)
  349.         HUnlock((Handle)globals);
  350.     
  351.     if (err!=noErr){
  352.         if (globals!=(GlobalsHandle)0){
  353.             DisposeHandle((Handle)globals);
  354.             SetComponentInstanceStorage(self,(Handle)0);
  355.         }
  356.     }
  357.     
  358.     return err;
  359. }
  360.  
  361. // handle the close request
  362. pascal ComponentResult ICGOClose(GlobalsHandle globals,ComponentInstance self){
  363.     if (globals!=(GlobalsHandle)0){
  364.         ICSOCleanGlobals(globals);
  365.         
  366.         if ((*globals)->delegate!=0)
  367.             CloseComponent((*globals)->delegate);
  368.         
  369.         DisposeHandle((Handle)globals);
  370.     }
  371.     
  372.     return noErr;
  373. }
  374.  
  375. // handle the target request
  376. pascal ComponentResult ICGOTarget(GlobalsHandle globals,ComponentInstance new_target){
  377.     ComponentResult err=noErr;
  378.     
  379.     (*globals)->target=new_target;
  380.     
  381.     if ((*globals)->delegate!=0)
  382.         err=ComponentSetTarget((*globals)->delegate,new_target);
  383.     
  384.     return err;
  385. }
  386.  
  387. // Internet Configuration specific routines
  388.  
  389. pascal ComponentResult main(ComponentParameters* params,Handle storage){
  390.     SignedByte s;
  391.     ComponentFunctionUPP proc;
  392.     ComponentResult res;
  393.     
  394. #if USESROUTINEDESCRIPTORS
  395.     __rsrcinit();
  396. #endif
  397.     
  398.     proc=(ComponentFunctionUPP)0;
  399.     
  400.     // DebugStr(SelectorToStr(params->what));
  401.     
  402.     switch (params->what){
  403.         // Component Manager Stuff
  404.         
  405.         case kComponentVersionSelect:
  406.             res=internetConfigurationComponentInterfaceVersion;
  407.             break;
  408.         case kComponentCanDoSelect:
  409.             proc=BuildNewProc(ICGOCanDo,uppICGOShortProcInfo);
  410.             break;
  411.         case kComponentOpenSelect:
  412.             proc=BuildNewProc(ICGOOpen,uppICGOInstanceProcInfo);
  413.             break;
  414.         case kComponentCloseSelect:
  415.             proc=BuildNewProc(ICGOClose,uppICGOInstanceProcInfo);
  416.             break;
  417.         case kComponentTargetSelect:
  418.             proc=BuildNewProc(ICGOTarget,uppICGOInstanceProcInfo);
  419.             break;
  420.         case kComponentRegisterSelect:
  421.             proc=BuildNewProc(ICGORegister,uppICGOGlobalsProcInfo);
  422.             break;
  423.         case kComponentUnregisterSelect:
  424.             proc=BuildNewProc(ICGOUnregister,uppICGOGlobalsProcInfo);
  425.             break;
  426.         
  427.         // this component type stuff
  428.         default:
  429.             proc=ICSOWhatToOverride((GlobalsHandle)storage,params->what);
  430.             break;
  431.     }
  432.     
  433.     if (storage!=(Handle)0){
  434.         s=HGetState(storage);
  435.         HLock(storage);
  436.     }
  437.     
  438.     res=delegateThisCallErr;
  439.     
  440.     if (proc!=(ComponentFunctionUPP)0){
  441.         res=CallComponentFunctionWithStorage(storage,params,proc);
  442.         DisposeRoutineDescriptor((UniversalProcPtr)proc);
  443.     }
  444.     
  445.     if ((storage!=(Handle)0)&&(params->what!=kComponentCloseSelect)){
  446.         HSetState(storage,s);
  447.     }
  448.     
  449. #if USESROUTINEDESCRIPTORS
  450.     __rsrcterm();
  451. #endif
  452.  
  453.     return res;
  454. }
  455.